#include "Calculator.h"
#include <iostream>

using namespace std;

Calculator::Calculator()
{
    this->operNumber = new stack<double>();
    this->operSign = new stack<char>();
    this->sign = true;
    this->pre = '#';
}

double Calculator::Calcualte(const string &s)
{
    this->s = s;
    if (this->Make_Str())
    {
        double ans = operNumber->top();
        operNumber->pop();
        return ans;
    }
    else
    {
        cout << "ERROR" << endl;
        return 0;
    }
}

bool Calculator::Make_Str()
{
    for (string::iterator it = this->s.begin(); it != this->s.end(); it++)
    {
        if (this->isNumber(*it))
        {
            double temp = 0.0;
            do
            {
                temp *= 10;
                temp += (*it - '0');
                pre = *it;
                it++;
            } while (this->isNumber(*it));

            if (*it == '.')
            {
                it++;
                double lesser = 0.1;
                while (this->isNumber(*it))
                {
                    temp += (*it - '0') * lesser;
                    lesser *= 0.1;
                    pre = *it;
                    it++;
                }
            }
            if (!sign)
            {
                temp = -temp;
                sign = true;
            }
            this->operNumber->push(temp);
        }
        else if (*it == '-' && (pre == '#' || pre == '('))
        {
            sign = false;
            it++;
        }
        else
        {
            if (!this->isLegalSign(*it))
            {
                cout << "ERROR INPUT STRING" << endl;
                return false;
            }
        }

        switch (this->Procede(*it))
        {
        case '<':
        {
            operSign->push(*it);
            pre = *it;
            it++;
            break;
        }
        case '=':
        {
            operSign->pop();
            pre = *it;
            it++;
            break;
        }
        case '>':
        {
            char oper = operSign->top();
            operSign->pop();
            double a = operNumber->top();
            operNumber->pop();
            double b = operNumber->top();
            operNumber->pop();

            operNumber->push(this->Compute(a, b, oper));

            break;
        }

        case 0:
        {
            cout << "ERROR ()" << endl;
            return false;
        }
        }
    }
    return true;
}

bool Calculator::isNumber(const char &ch)
{
    if (ch >= '0' && ch <= '9')
    {
        return true;
    }
    return false;
}

double Calculator::Compute(const double &a, const double &b, const char &oper)
{
    if (oper == '+')
    {
        return a + b;
    }
    if (oper == '-')
    {
        return a - b;
    }
    if (oper == '*')
    {
        return a * b;
    }
    if (oper == '/')
    {
        return a / b;
    }
}

char Calculator::Procede(const char &oper)
{
    char top = this->operSign->top();
    if (top == '+' || top == '-')
    {
        if (oper == '*' || oper == '/' || oper == '(')
        {
            return '<';
        }
        return '>';
    }
    if (top == '*' || top == '/')
    {
        if (oper == '(')
        {
            return '<';
        }
        return '>';
    }
    if (top == '(')
    {
        if (oper == ')')
        {
            return '=';
        }
        else if (oper != '#')
        {
            return '<';
        }
    }
    return 0;
}

bool Calculator::isLegalSign(const char &ch)
{
    if (ch == '+' || ch == '-' || ch == '*' || ch == '/')
    {
        return true;
    }
    return false;
}

Calculator::~Calculator()
{
}